#include "include.h"

/****************************************************************
 *This function is thread4
 *	(1)create socket,listen port,process command
 ****************************************************************/
void *thread4(void *str)
{
	unsigned int temp_i = 0, temp_k = 0, rd_data, opt_place = 0, net_send_len = 0;

	unsigned int timeout = 0;
	unsigned int fifo_len_valid = 0;

    // 建立发送组播套接字
	int sock_send;
	sock_send = socket(AF_INET, SOCK_DGRAM, 0);

	struct in_addr opt;
    inet_pton(AF_INET, ONE_LO_PCM_BOARDCAST_IP, &opt.s_addr);
    setsockopt(sock_send, IPPROTO_IP, IP_MULTICAST_IF, &opt, sizeof(opt));
    struct sockaddr_in cliaddr;
    int len = sizeof(cliaddr);
    cliaddr.sin_family = AF_INET;
    cliaddr.sin_port = htons(ONE_LO_PCM_BOARDCAST_PORT);
    inet_pton(AF_INET, ONE_LO_PCM_BOARDCAST_IP, &cliaddr.sin_addr.s_addr);

	// 给出线程运行提示信息
	fprintf(stderr,"thread four running\n");

	/////*************  测试用，上电后自动启动FPGA的PCM组播，此为开始部分   ************//////
	// 上电自动配置参数

	// 停止PCM码流
	//dev_32bit_write(mmap_addr, 0x8, 0x65);
	//usleep(10000);
/*
    // 复位FPGA
    dev_32bit_write(mmap_addr, 0x00, 0);
    usleep(1000);
    dev_32bit_write(mmap_addr, 0x00, 1);
    usleep(1000);

    // PCM通用参数设置
    dev_32bit_write(mmap_addr, 0x4000, 0x55);               // 基带数据处理板卡工作模式为仿真模式
    dev_32bit_write(mmap_addr, 0x4004, 0x670bc502);         // 8.192Mbps的CY22393输出CLKA时钟（明文）
    dev_32bit_write(mmap_addr, 0x4008, 0x670bc502);         // 8.192Mbps的CY22393输出CLKB时钟（密文）
    dev_32bit_write(mmap_addr, 0x400C, 0x5);                // 22393输出时钟的分频系数（8.192Mbps——0x5）
    dev_32bit_write(mmap_addr, 0x4010, 0x55);               // 信号极性——正向
    dev_32bit_write(mmap_addr, 0x4014, 0x0);                // 解调FPGA输入码型，NRZ-L码

    // PCM子帧参数设置说明
    dev_32bit_write(mmap_addr, 0x4018, 0x0);                // 子帧字长8bit
    dev_32bit_write(mmap_addr, 0x401c, 0x9ff);              // 子帧长度320
    dev_32bit_write(mmap_addr, 0x4020, 0x9abcb52c);         // 子帧同步码0x9abcb52c
    dev_32bit_write(mmap_addr, 0x4024, 0xffffffff);         // 子帧同步码掩码
    dev_32bit_write(mmap_addr, 0x4028, 0x1f);               // 帧同步码组位数

	// PCM副帧参数设置说明		
    dev_32bit_write(mmap_addr, 0x402c, 0x2);                // 副帧方式——反码副帧
    dev_32bit_write(mmap_addr, 0x4030, 0xf);                // 副帧长度——16子帧
    dev_32bit_write(mmap_addr, 0x4034, 0x9fff);             // 副帧长——16×320×8-1
    dev_32bit_write(mmap_addr, 0x4038, 0x65434ad3);         // 副帧同步码
    dev_32bit_write(mmap_addr, 0x403c, 0xffffffff);         // 副帧同步码掩码
    dev_32bit_write(mmap_addr, 0x4040, 0xffffffff);         // ID字位置——反码副帧不适用
    dev_32bit_write(mmap_addr, 0x4044, 0x0);                // ID字基值——反码副帧不适用
    dev_32bit_write(mmap_addr, 0x4048, 0xf0);               // ID计数方向——反码副帧不适用
    dev_32bit_write(mmap_addr, 0x404c, 0x3);                // 校核检测帧数
    dev_32bit_write(mmap_addr, 0x4050, 0x3);                // 惯性同步帧数	

	// PCM仿真源参数设置说明		
    dev_32bit_write(mmap_addr, 0x4054, 0x1);                // 码源类型
    dev_32bit_write(mmap_addr, 0x4058, 0x4);                // 同步码长
    dev_32bit_write(mmap_addr, 0x405c, 0x13c);              // 去帧头数据长
    dev_32bit_write(mmap_addr, 0x4060, 0xf0139);            // 副帧计数位置

	// PCM中断区参数设置说明		
    dev_32bit_write(mmap_addr, 0x4064, 0x3D8);              // 解调数据缓存长度

    // PCM时统参数设置说明		
    dev_32bit_write(mmap_addr, 0x4068, 0x0);                // 时码模式——内时统
    dev_32bit_write(mmap_addr, 0x406c, 0x14130000);         // 内时统基准时间，低32位
    dev_32bit_write(mmap_addr, 0x4070, 0x000001C3);         // 内时统基准时间，高32位
	
    // PCM译码解密参数设置说明	
    dev_32bit_write(mmap_addr, 0x4074, 0x0);                // 不加密不编码
    dev_32bit_write(mmap_addr, 0x4078, 0x1ACFFC1D);         // TPC块同步码组
	for(temp_i=0;temp_i<23;temp_i++)
	{
        dev_32bit_write(mmap_addr, (0x407C + temp_i * 4), 0xffffffff);         // 密钥位置
	}
	for(temp_i=0;temp_i<1024;temp_i++)
	{
        dev_32bit_write(mmap_addr, (0x40d8 + temp_i * 4), 0xffffffff);         // 非加密字段
	}	

    // 参数下注完成	
    dev_32bit_write(mmap_addr, 0x4, 0x1);                
    pcm_once_read_len = 246;
    pcm_once_read_len_two = 246;

	// 启动工作，PCM工作
    dev_32bit_write(mmap_addr, 0x8, 0x9a); 
*/

	/////*************  测试用，上电后自动启动FPGA的PCM组播，此为停止部分   ************//////

	while(1){
		// 延时查询
		usleep(100);

		// 读取HDLC缓冲区中数据大小
		pcm_rd_date_length = 0;
		dev_32bit_read(mmap_addr, 0x10, &pcm_rd_date_length);

		// 输出FIFO是否满
		if(pcm_rd_date_length > 2000){
			fprintf(stderr,"1:%d\n", pcm_rd_date_length);
		}

		// 判断fifo的数据区是否有效
		fifo_len_valid = 0;
		fifo_len_valid = pcm_rd_date_length & 0xfffff800;
		if(fifo_len_valid != 0){
			continue;
		}

		// 获取有效数据的长度
		pcm_rd_date_length &= 0x7ff;
		if(pcm_rd_date_length >= pcm_once_read_len){
			// 超时清空
			timeout = 0;

			// 读取数据
			for(temp_i = 0; temp_i < pcm_once_read_len; temp_i ++){
				opt_place = temp_i * 4;
				dev_32bit_read(mmap_addr, 0x18, &rd_data); 
				pcm_rd_data_buffer[opt_place + 0] = (char)(rd_data >> 24);
				pcm_rd_data_buffer[opt_place + 1] = (char)(rd_data >> 16);
				pcm_rd_data_buffer[opt_place + 2] = (char)(rd_data >> 8);
				pcm_rd_data_buffer[opt_place + 3] = (char)(rd_data >> 0);
			}

			// 组播发送
			net_send_len = pcm_once_read_len << 2;
			sendto(sock_send, pcm_rd_data_buffer, net_send_len, 0, \
					(struct sockaddr*)&cliaddr, len);

			// 开始存储后，才进行数据填充
			if((pcm_store_status == START_PCM_STORE) && (pcm_store_fd > 0)){
				// 当前正在使用存储区1，进行数据存储
				if(pcm_store_flag == PCM_STORE_USE_ONE){
					for(temp_k = 0; temp_k < net_send_len; temp_k ++){
						// 填充数据域
						pcm_one_store_buff_1[pcm_one_store_len_1 + temp_k] = pcm_rd_data_buffer[temp_k];
					}
					pcm_one_store_len_1 += net_send_len;
					single_store_len += net_send_len;

					if(pcm_one_store_len_1 >= PCM_STORE_UP_LIMIT){
						thread_pcm_store_len += pcm_one_store_len_1;
						pcm_store_flag = PCM_STORE_USE_TWO;
					}
				} else if(pcm_store_flag == PCM_STORE_USE_TWO){
					for(temp_k = 0; temp_k < net_send_len; temp_k ++){
						// 填充数据域
						pcm_one_store_buff_2[pcm_one_store_len_2 + temp_k] = pcm_rd_data_buffer[temp_k];
					}
					pcm_one_store_len_2 += net_send_len;
					single_store_len += net_send_len;

					if(pcm_one_store_len_2 >= PCM_STORE_UP_LIMIT){
						thread_pcm_store_len += pcm_one_store_len_2;
						pcm_store_flag = PCM_STORE_USE_ONE;
					}
				} else {
					;
				}
			}
		} else if((pcm_rd_date_length > 0) && (pcm_rd_date_length < pcm_once_read_len)){
			// 超时增加个
			timeout ++;
			if(timeout >= 10000){
				timeout = 0;

				// 读取数据
				for(temp_i = 0; temp_i < pcm_rd_date_length; temp_i ++){
					opt_place = temp_i * 4;
					dev_32bit_read(mmap_addr, 0x18, &rd_data); 
					pcm_rd_data_buffer[opt_place + 0] = (char)(rd_data >> 24);
					pcm_rd_data_buffer[opt_place + 1] = (char)(rd_data >> 16);
					pcm_rd_data_buffer[opt_place + 2] = (char)(rd_data >> 8);
					pcm_rd_data_buffer[opt_place + 3] = (char)(rd_data >> 0);
				}

				// 组播发送
				net_send_len = pcm_rd_date_length << 2;
				sendto(sock_send, pcm_rd_data_buffer, net_send_len, 0, \
						(struct sockaddr*)&cliaddr, len);

				// 开始存储后，才进行数据填充
				if((pcm_store_status == START_PCM_STORE) && (pcm_store_fd > 0)){
					// 当前正在使用存储区1，进行数据存储
					if(pcm_store_flag == PCM_STORE_USE_ONE){
						for(temp_k = 0; temp_k < net_send_len; temp_k ++){
							// 填充数据域
							pcm_one_store_buff_1[pcm_one_store_len_1 + temp_k] = pcm_rd_data_buffer[temp_k];
						}
						pcm_one_store_len_1 += net_send_len;
						single_store_len += net_send_len;

						if(pcm_one_store_len_1 >= PCM_STORE_UP_LIMIT){
							thread_pcm_store_len += pcm_one_store_len_1;
							pcm_store_flag = PCM_STORE_USE_TWO;
						}
					} else if(pcm_store_flag == PCM_STORE_USE_TWO){
						for(temp_k = 0; temp_k < net_send_len; temp_k ++){
							// 填充数据域
							pcm_one_store_buff_2[pcm_one_store_len_2 + temp_k] = pcm_rd_data_buffer[temp_k];
						}
						pcm_one_store_len_2 += net_send_len;
						single_store_len += net_send_len;

						if(pcm_one_store_len_2 >= PCM_STORE_UP_LIMIT){
							thread_pcm_store_len += pcm_one_store_len_2;
							pcm_store_flag = PCM_STORE_USE_ONE;
						}
					} else {
						;
					}
				}
			}
		} else {
			;
		}
	}

	return NULL;
}

